#include <fstream>
#include <iostream>
#include <logger.hpp>
#include <server/frame/PollServer.h>
#include <server/frame/TcpRecver.h>
#include <server/frame/CmdDecoder.h>
#include <server/CmdHandler.h>
#include "ServerStatistic.h"

CServerStatistic::CServerStatistic(CMainServer & mainServer)
    : CThreadPool(1,mainServer.serverStatsStackSz_)
    , config_(mainServer.config_)
    , addingFd_(mainServer.addingFd_)
    , readableFdQue_(mainServer.readableFdQue_)
    , fdSockMap_(mainServer.fdSockMap_)
    , decodableCmdQue_(mainServer.decodableCmdQue_)
    , queryCmdQue_(mainServer.queryCmdQue_)
    , request_(mainServer.request_)
    , recver_(*mainServer.recver_)
    , cmdDecoder_(*mainServer.cmdDecoder_)
    , cmdHandler_(*mainServer.cmdHandler_)
{}

void CServerStatistic::Init()
{
    serverStatusFile_           = config_.GetString("server.stats.file.name");
    serverStatusTimeInterval_   = config_.GetInt("server.stats.time.interval",30,5);
    serverStatusFile_ += Tools::TimeString(time(0),".%Y%m%d%H%M%S");
}

void CServerStatistic::Reconfig()
{
    serverStatusTimeInterval_   = config_.GetInt("server.stats.time.interval",30,5);
}

void CServerStatistic::ShowConfig() const
{
    using namespace std;
    cout<<"\nServerStatistic :\n"
        <<"  serverStatusFile_ = "<<serverStatusFile_<<endl
        <<"  serverStatusTimeInterval_ = "<<serverStatusTimeInterval_<<endl;
}

int CServerStatistic::doIt()
{
    LOG(DEBUG, "CServerStatistic::doIt");
    //header info
    LOG(DEBUG, "open server status file "<<serverStatusFile_);
    std::ofstream outf(serverStatusFile_.c_str());
    if(!outf.is_open()){
        LOG(ERROR, "cannot open server status file="<<serverStatusFile_);
    }else{
        outf<<"Time"
            <<"\t"<<"request_"
            <<"\t"<<"addingFd_.Size()"<<"\t"<<"addingFd_.TopSize()"
            <<"\t"<<"readableFdQue_.Size()"<<"\t"<<"readableFdQue_.TopSize()"
            <<"\t"<<"fdSockMap_.Size()"
            <<"\t"<<"decodableCmdQue_.Size()"<<"\t"<<"decodableCmdQue_.TopSize()"
            <<"\t"<<"queryCmdQue_.Size()"<<"\t"<<"queryCmdQue_.TopSize()"
            <<"\t"<<"recver_.ActiveCount()"<<"\t"<<"recver_.ActiveMax()"
            <<"\t"<<"cmdDecoder_.ActiveCount()"<<"\t"<<"cmdDecoder_.ActiveMax()"
            <<"\t"<<"cmdHandler_.ActiveCount()"<<"\t"<<"cmdHandler_.ActiveMax()"
            <<std::endl;
        outf.close();
    }
    for(;;){
        sleep(serverStatusTimeInterval_);
        LOG(DEBUG, "open server status file "<<serverStatusFile_<<" and write");
        outf.open(serverStatusFile_.c_str(),std::ios_base::app);
        if(!outf.is_open()){
            LOG(ERROR, "cannot open server status file="<<serverStatusFile_<<CSocket::ErrMsg());
        }else{
            outf<<Tools::TimeString(time(0));
            outf<<"\t"<<request_;
            request_ = 0;
            outf<<"\t"<<addingFd_.Size()<<"\t"<<addingFd_.TopSize();
            addingFd_.ResetTopSize();
            outf<<"\t"<<readableFdQue_.Size()<<"\t"<<readableFdQue_.TopSize();
            readableFdQue_.ResetTopSize();
            outf<<"\t"<<fdSockMap_.Size();
            outf<<"\t"<<decodableCmdQue_.Size()<<"\t"<<decodableCmdQue_.TopSize();
            decodableCmdQue_.ResetTopSize();
            outf<<"\t"<<queryCmdQue_.Size()<<"\t"<<queryCmdQue_.TopSize();
            queryCmdQue_.ResetTopSize();
            outf<<"\t"<<recver_.ActiveCount()<<"\t"<<recver_.ActiveMax();
            recver_.ResetActive();
            outf<<"\t"<<cmdDecoder_.ActiveCount()<<"\t"<<cmdDecoder_.ActiveMax();
            cmdDecoder_.ResetActive();
            outf<<"\t"<<cmdHandler_.ActiveCount()<<"\t"<<cmdHandler_.ActiveMax();
            cmdHandler_.ResetActive();
            outf<<std::endl;
            outf.close();
        }
    }
    return 0;
}
